package com.alibaba.citrus.cr.unified.inventory.repository.impl;

import com.alibaba.citrus.cr.common.exception.FacadeException;
import com.alibaba.citrus.cr.common.util.PageUtils;
import com.alibaba.citrus.cr.unified.inventory.repository.AllocateOrderReadRepository;
import com.alibaba.citrus.cr.unified.inventory.utils.EnumUtils;
import com.alibaba.citrus.cr.unified.inventory.utils.InfoUtil;
import com.alibaba.citrus.cr.common.annotation.RepositoryInvoker;
import com.alibaba.citrus.cr.common.util.JsonUtil;
import com.alibaba.citrus.cr.common.util.NameUtil;
import com.alibaba.citrus.cr.common.util.TimeUtil;
import com.alibaba.cz.base.tool.Nullable;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.lattice2.epoch.sdk.model.Result;
import com.alibaba.lattice2.epoch.user.dto.LoginUser;
import com.alibaba.lattice2.epoch.user.service.EpochLoginUserService;
import com.epoch.app.bcorder.model.dto.QueryCargoZoneByIdRequest;
import com.epoch.app.bcorder.model.dto.QueryCargoZoneByIdResponse;
import com.epoch.app.bcorder.model.dto.*;
import com.epoch.app.bcorder.service.BaseDataService;
import com.epoch.app.bcorder.service.UnifiedInventoryService;
import com.epoch.app.crplatformenhance.model.dto.GetOrganiztionByIdRequest;
import com.epoch.app.crplatformenhance.model.dto.PageQueryAddressListRequest;
import com.epoch.app.crplatformenhance.model.dto.PageQueryAddressListResponse;
import com.epoch.app.crplatformenhance.sdo.OrganizationSDO;
import com.epoch.app.crplatformenhance.service.CrPlatformEnhanceService;
import com.epoch.app.crunifiedinventory.domain.allocateapplyorder.dto.LoadAllocateApplyOrderRequest;
import com.epoch.app.crunifiedinventory.domain.allocateapplyorder.model.AllocateApplyOrder;
import com.epoch.app.crunifiedinventory.domain.allocateapplyorder.service.AllocateApplyOrderService;
import com.epoch.app.crunifiedinventory.domain.allocateorder.dto.*;
import com.epoch.app.crunifiedinventory.domain.allocateorder.dto.AllocateOrderLoadListRequest;
import com.epoch.app.crunifiedinventory.domain.allocateorder.model.AllocateOrder;
import com.epoch.app.crunifiedinventory.domain.allocateorder.service.AllocateOrderService;
import com.epoch.app.crunifiedinventory.domain.allocateorderdetail.dto.AllocateOrderDetailLoadListRequest;
import com.epoch.app.crunifiedinventory.domain.allocateorderdetail.dto.QueryFrozenOrderDetailListRequest;
import com.epoch.app.crunifiedinventory.domain.allocateorderdetail.dto.QueryListByIdsRequest;
import com.epoch.app.crunifiedinventory.domain.allocateorderdetail.dto.QueryListByIdsResponse;
import com.epoch.app.crunifiedinventory.domain.allocateorderdetail.dto.QueryListForStatCreditRequest;
import com.epoch.app.crunifiedinventory.domain.allocateorderdetail.dto.QueryUnconfirmedOrderDetailListRequest;
import com.epoch.app.crunifiedinventory.domain.allocateorderdetail.model.AllocateOrderDetail;
import com.epoch.app.crunifiedinventory.domain.allocateorderdetail.service.AllocateOrderDetailService;
import com.epoch.app.crunifiedinventory.dto.request.AllocateOrderDetailSearchRequest;
import com.epoch.app.crunifiedinventory.dto.request.AllocateOrderGetCustomerRequest;
import com.epoch.app.crunifiedinventory.dto.request.AllocateOrderGetWarehouseRequest;
import com.epoch.app.crunifiedinventory.dto.request.AloocateOrderGetTransRequest;
import com.epoch.app.crunifiedinventory.dto.request.*;
import com.epoch.app.crunifiedinventory.dto.response.*;
import com.epoch.app.crunifiedinventory.dto.response.AllocateOrderBatchGetWarehouseResponse;
import com.epoch.app.crunifiedinventory.model.dto.*;
import com.epoch.app.crunifiedinventory.model.dto.AllocateOrderScItemDetailDTO;
import com.epoch.app.crunifiedinventory.model.enums.CreditCheckStatus;
import com.epoch.app.crunifiedinventory.model.enums.WmsStatusEnum;
import com.epoch.app.crunifiedinventory.ouiallocateorderdetailindex.model.OuiAllocateOrderDetailIndex;
import com.epoch.app.crunifiedinventory.ouiallocateorderdetailindex.service.OuiAllocateOrderDetailIndexService;
import com.epoch.app.crunifiedinventory.sdo.AllocateOrderDetailSDO;
import com.epoch.app.crunifiedinventory.sdo.AllocateOrderSDO;
import com.epoch.app.crunifiedinventory.sdo.AllocateOrderWithOrderDetailsSDO;
import com.epoch.app.crunifiedinventory.service.CrUnifiedInventoryService;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @description:
 * @author: yuhw
 * @date: 2021年09月16日 19:38
 **/
@Component
public class AllocateOrderReadRepositoryImpl implements AllocateOrderReadRepository {

    private Log log = Log.getLogger(AllocateOrderReadRepositoryImpl.class);

    private final static int MAX_PAGE_SIZE=1000;

    @Resource
    AllocateOrderService allocateOrderService;
    @Resource
    AllocateApplyOrderService allocateApplyOrderService;
    @Resource
    AllocateOrderDetailService allocateOrderDetailService;

    @Resource
    BaseDataService baseDataService;
    @Resource
    UnifiedInventoryService unifiedInventoryService;
    @Autowired
    CrPlatformEnhanceService otsPlatformEnhanceService;
    @Resource
    OuiAllocateOrderDetailIndexService ouiAllocateOrderDetailIndexService;
    @Resource
    CrUnifiedInventoryService otsUnifiedInventoryService;
    @Resource
    EpochLoginUserService epochLoginUserService;
    @Resource(name = "logsCheckSyncTaskExecutor")
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    /**
     * 获取主单和明细
     * @param request
     * @return
     */
    @Override
    public AllocateOrderInfo find(AllocateOrderRequest request) {
        AllocateOrderInfo allocateOrderInfo = new AllocateOrderInfo();
        if (StringUtils.isNotBlank(request.getAllocateOrderId())){
            LoadAllocateOrderRequest loadAllocateOrderRequest = new LoadAllocateOrderRequest();
            loadAllocateOrderRequest.setId(request.getAllocateOrderId());
            AllocateOrder allocateOrder = allocateOrderService.loadAllocateOrder(loadAllocateOrderRequest);
            allocateOrderInfo = JsonUtil.convert(allocateOrder,AllocateOrderInfo.class);
        }else if (StringUtils.isNotBlank(request.getAllocateOrderCode())){
            AllocateOrderLoadListRequest allocateOrderLoadListRequest = new AllocateOrderLoadListRequest();
            allocateOrderLoadListRequest.setCode(request.getAllocateOrderCode());
            allocateOrderLoadListRequest.setDir("id");
            allocateOrderLoadListRequest.setAsc(false);
            Result<List<AllocateOrder>>  result = allocateOrderService.loadAllocateOrderList(allocateOrderLoadListRequest);
            if (result == null || CollectionUtils.isEmpty(result.getResult())){
                return null;
            }
            AllocateOrder allocateOrder = result.getResult().get(0);
            allocateOrderInfo = JsonUtil.convert(allocateOrder,AllocateOrderInfo.class);
        }else {
            return null;
        }
        if (allocateOrderInfo == null || allocateOrderInfo.getId() == null){
            return null;
        }
        AllocateOrderDetailLoadListRequest allocateOrderDetailLoadListRequest = new AllocateOrderDetailLoadListRequest();
        allocateOrderDetailLoadListRequest.setAllocateOrderId(allocateOrderInfo.getId());
        allocateOrderDetailLoadListRequest.setLimit(MAX_PAGE_SIZE);
        Result<List<AllocateOrderDetail>> result =
                allocateOrderDetailService.loadAllocateOrderDetailList(allocateOrderDetailLoadListRequest);
        if (result == null || CollectionUtils.isEmpty(result.getResult())){
            return allocateOrderInfo;
        }
        allocateOrderInfo.setDetails(result.getResult());

        return allocateOrderInfo;
    }

    @Override
    public AllocateOrderWithOrderDetailsSDO get(AllocateOrderRequest request) {
//        ouiAllocateOrderDetailIndexService.loadOuiAllocateOrderDetailIndex()
        AllocateOrderSDO allocateOrderSDO;
        if (StringUtils.isNotBlank(request.getAllocateOrderId())){
            LoadAllocateOrderRequest loadAllocateOrderRequest = new LoadAllocateOrderRequest();
            loadAllocateOrderRequest.setId(request.getAllocateOrderId());
            AllocateOrder allocateOrder = allocateOrderService.loadAllocateOrder(loadAllocateOrderRequest);
            allocateOrderSDO = JsonUtil.convert(allocateOrder,AllocateOrderSDO.class);
        }else if (StringUtils.isNotBlank(request.getAllocateOrderCode())||StringUtils.isNotBlank(request.getOutAllocateOrderId())){
            AllocateOrderLoadListRequest allocateOrderLoadListRequest = new AllocateOrderLoadListRequest();
            allocateOrderLoadListRequest.setCode(request.getAllocateOrderCode());
            allocateOrderLoadListRequest.setOutAllocateOrderId(request.getOutAllocateOrderId());
            allocateOrderLoadListRequest.setDir("id");
            allocateOrderLoadListRequest.setAsc(false);
            log.info("AllocateOrderReadRepositoryImpl.get.loadAllocateOrderList,code:{},data:{}",request.getAllocateOrderCode(),JSON.toJSONString(allocateOrderLoadListRequest));
            Result<List<AllocateOrder>>  result = allocateOrderService.loadAllocateOrderList(allocateOrderLoadListRequest);
            log.info("AllocateOrderReadRepositoryImpl.get.loadAllocateOrderList,code:{},loadAllocateOrderListResult:{}",request.getAllocateOrderCode(),JSON.toJSONString(result));
            if (result == null || CollectionUtils.isEmpty(result.getResult())){
                return null;
            }
            AllocateOrder allocateOrder = result.getResult().get(0);
            allocateOrderSDO = JsonUtil.convert(allocateOrder,AllocateOrderSDO.class);
        }  else {
            return null;
        }
        if (allocateOrderSDO == null || allocateOrderSDO.getId() == null){
            return null;
        }
        AllocateOrderWithOrderDetailsSDO sdo = new AllocateOrderWithOrderDetailsSDO();
        sdo.setAllocateOrderSDO(allocateOrderSDO);
        AllocateOrderDetailLoadListRequest allocateOrderDetailLoadListRequest = new AllocateOrderDetailLoadListRequest();
        allocateOrderDetailLoadListRequest.setAllocateOrderId(allocateOrderSDO.getId());
        //调拨单最大行数为500
        allocateOrderDetailLoadListRequest.setLimit(MAX_PAGE_SIZE);
        Result<List<AllocateOrderDetail>> result =
        allocateOrderDetailService.loadAllocateOrderDetailList(allocateOrderDetailLoadListRequest);
        if (result == null || CollectionUtils.isEmpty(result.getResult())){
            return sdo;
        }
        List<AllocateOrderDetailSDO> detailSDOS = JsonUtil.convertList(result.getResult(),AllocateOrderDetailSDO.class);
        sdo.setAllocateOrderDetailSDOS(detailSDOS);
        //大于默认的最大条数 循环查询拼装起来
        if (result.getTotal() > MAX_PAGE_SIZE){
            int max = result.getTotal() % MAX_PAGE_SIZE == 0 ? result.getTotal() / MAX_PAGE_SIZE: result.getTotal() /MAX_PAGE_SIZE + 1;
            for (int i=1;i<max;i++){
                allocateOrderDetailLoadListRequest.setAllocateOrderId(allocateOrderSDO.getId());
                allocateOrderDetailLoadListRequest.setStart( i *MAX_PAGE_SIZE);
                allocateOrderDetailLoadListRequest.setLimit(MAX_PAGE_SIZE);
                Result<List<AllocateOrderDetail>> listResult = allocateOrderDetailService.loadAllocateOrderDetailList(allocateOrderDetailLoadListRequest);
                if (listResult != null && CollectionUtils.isNotEmpty(listResult.getResult())){
                    detailSDOS.addAll(JsonUtil.convertList(listResult.getResult(),AllocateOrderDetailSDO.class));
                }
            }
            sdo.setAllocateOrderDetailSDOS(detailSDOS);
        }

        return sdo;
    }

    /**
     * 调拨单详情
     * @param allocateOrderDetailsQueryRequest
     * @return
     */
    @Override
    public AllocateOrderDetailsQueryResponse queryDetail(AllocateOrderDetailsQueryRequest allocateOrderDetailsQueryRequest) {
        AllocateOrderLoadListRequest request = new AllocateOrderLoadListRequest();
        AllocateOrderDetailsQueryResponse response = new AllocateOrderDetailsQueryResponse();
        if (StringUtils.isNotBlank(allocateOrderDetailsQueryRequest.getAllocateOrderId())){
            request.setId(Long.valueOf(allocateOrderDetailsQueryRequest.getAllocateOrderId()));
        }else if(StringUtils.isNotBlank(allocateOrderDetailsQueryRequest.getCode())){
            request.setCode(allocateOrderDetailsQueryRequest.getCode());
        }else if(StringUtils.isNotBlank(allocateOrderDetailsQueryRequest.getOutAllocateOrderId())){
            request.setOutAllocateOrderId(allocateOrderDetailsQueryRequest.getOutAllocateOrderId());
        }else {
            if (StringUtils.isNotBlank(allocateOrderDetailsQueryRequest.getThirdAllocateOrderId())) {
                request.setThirdAllocateOrderId(allocateOrderDetailsQueryRequest.getThirdAllocateOrderId());
            }else {
                return null;
            }
        }

        if(StringUtils.isNotBlank(allocateOrderDetailsQueryRequest.getFromSys())){
            request.setFromSys(allocateOrderDetailsQueryRequest.getFromSys());
        }
        if(StringUtils.isNotBlank(allocateOrderDetailsQueryRequest.getBusinessType())){
            request.setBusinessType(allocateOrderDetailsQueryRequest.getBusinessType());
        }
        Result<List<AllocateOrder>> result = allocateOrderService.loadAllocateOrderList(request);
        if (result == null || CollectionUtils.isEmpty(result.getResult())){
            return response;
        }
        AllocateOrder allocateOrder = result.getResult().get(0);
        AllocateApplyOrder allocateApplyOrder = new AllocateApplyOrder();
        if (StringUtils.isNotBlank(allocateOrder.getAllocateApplyOrderId())){
            LoadAllocateApplyOrderRequest loadAllocateApplyOrderRequest = new LoadAllocateApplyOrderRequest();
            loadAllocateApplyOrderRequest.setId(allocateOrder.getAllocateApplyOrderId());
            AllocateApplyOrder allocateApplyOrderResult = allocateApplyOrderService.loadAllocateApplyOrder(loadAllocateApplyOrderRequest);
            if (allocateApplyOrderResult != null){
                allocateApplyOrder = allocateApplyOrderResult;
            }
        }
        response.setId(allocateOrder.getId());
        response.setCode(allocateOrder.getCode());
        response.setType(allocateOrder.getType());
        response.setTypeDesc(EnumUtils.getAllocateOrderType(allocateOrder.getType()));
        //提报组织
        if (StringUtils.isNotBlank(allocateOrder.getApplyOrgId())){
            AllocateOrderGetOrganizationResponse organizationResponse = InfoUtil.getOrganizationById(allocateOrder.getApplyOrgId());
            response.setApplyOrgName(organizationResponse.getName());
        }
        response.setProductGroup("11");
        response.setProductGroupDesc("常温");
        response.setReturnOrder(allocateOrder.getReturnOrder());
        response.setReturnOrderDesc(Objects.equals(Boolean.TRUE,allocateOrder.getReturnOrder())?"是":"否");
        response.setIsDTC(allocateOrder.getIsDTC());
        response.setIsDTCDesc(Objects.equals(allocateOrder.getIsDTC(),Boolean.TRUE)?"是":"否");
        response.setAddressCode(allocateOrder.getAddressCode());
        response.setAllocateApplyOrderCode(allocateApplyOrder.getCode());
        response.setBusinessType(allocateOrder.getBusinessType());
        response.setFromSys(allocateOrder.getFromSys());
        //调拨单外部单号，如果nykid有值取nykid，没有取原有的外部单号
        response.setOutAllocateOrderId(StringUtils.isNotBlank(allocateOrder.getNykId())?allocateOrder.getNykId():allocateOrder.getOutAllocateOrderId());
        response.setCreateTime(allocateOrder.getCreateTime()==null?allocateOrder.getGmt_create():allocateOrder.getCreateTime());
        response.setCreator(NameUtil.getRealName(allocateOrder.getCreator()));
        response.setCreatorId(NameUtil.getEmpId(allocateOrder.getCreator()));
        response.setRemark(allocateOrder.getRemark());
        // TODO 总部客户

        WmsSDO receiveWmsSDO = InfoUtil.getWmsSDO(allocateOrder.getReceiveAreaId());
        if (receiveWmsSDO != null){
            AllocateOrderGetCustomerResponse customer = InfoUtil.getCustomer(receiveWmsSDO.getSapDeliveryBPCode());
            if (customer != null){
                response.setSapCustomerName(customer.getCustomerName());
                response.setSapCustomerAddress(customer.getCustomerAddress());
                response.setSapCustomerAddressName(customer.getCustomerAddressName());
            }
        }
        response.setExpectedDeliveryDate(allocateOrder.getExpectedDeliveryDate());
        response.setExpectedDeliveryDateStr(TimeUtil.formatYYYY_MM_dd(allocateOrder.getExpectedDeliveryDate()));
        response.setDocDate(allocateOrder.getDocDate());
        response.setDocDateStr(TimeUtil.formatYYYY_MM_dd(allocateOrder.getDocDate()));
        response.setUpdateTime(allocateOrder.getGmt_modified());
        response.setOrderReasonDesc(EnumUtils.getOrderReason(allocateOrder.getOrderReason()));
        response.setModifier(NameUtil.getRealName(allocateOrder.getUpdater()));

        //客户信息
//        AllocateOrderGetCustomerResponse customer = InfoUtil.getCustomer(allocateOrder.getCustomer());
        AllocateOrderGetCustomerResponse customer = InfoUtil.getCustomerByAddressCode(allocateOrder.getAddressCode());
        if (customer != null){
            response.setCustomerAddress(customer.getCustomerAddress());
            response.setCustomerAddressName(customer.getCustomerAddressName());
            response.setCustomerName(customer.getCustomerName());
            response.setCustomer(customer.getCustomer());
        }
        WmsSDO shipWmsSDO = InfoUtil.getWmsSDO(allocateOrder.getShipAreaId());
        response.setShipAreaId(allocateOrder.getShipAreaId());
        response.setReceiveAreaId(allocateOrder.getReceiveAreaId());
        response.setShipWarehouseId(allocateOrder.getShipWarehouseId());
        response.setReceiveWarehouseId(allocateOrder.getReceiveWarehouseId());
        response.setNykId(allocateOrder.getNykId());
        if (shipWmsSDO !=null){
            response.setShipAreaName(shipWmsSDO.getName());
            AllocateOrderGetOrganizationResponse shipOrg = InfoUtil.getOrganizationById(shipWmsSDO.getSapSalesOrgId());
            if (shipOrg != null){
                response.setShipAreaOrgName(shipOrg.getName());
                response.setShipOrgName(shipOrg.getName());
            }
        }
        if (receiveWmsSDO != null){
            response.setReceiveAreaName(receiveWmsSDO.getName());
//            AllocateOrderGetOrganizationResponse receiveOrg = InfoUtil.getOrganizationById(receiveWmsSDO.getSapSalesOrgId());
            AllocateOrderGetOrganizationResponse receiveOrg = InfoUtil.getOrganizationById(allocateOrder.getReceiveOrgId());
            if (receiveOrg != null){
                response.setReceiveAreaOrgName(receiveOrg.getName());
                response.setReceiveOrgName(receiveOrg.getName());
            }
        }
        response.setShipMethod(allocateOrder.getShipMethod());
        response.setShipMethodDesc(InfoUtil.getShipMethodDesc(allocateOrder.getShipMethod()));
        response.setOrderReasonDesc(EnumUtils.getOrderReason(allocateOrder.getOrderReason()));
        if (receiveWmsSDO != null){
            response.setSapInternalSalesBPCode(receiveWmsSDO.getSapInternalSalesBPCode());
            response.setSapInternalDeliveryBPCode(receiveWmsSDO.getSapInternalDeliveryBPCode());
            response.setSapDeliveryBPCode(receiveWmsSDO.getSapDeliveryBPCode());
            response.setSapSalesBPCode(receiveWmsSDO.getSapSalesBPCode());
        }
        response.setSapCostCenter(allocateOrder.getSapCostCenter());
        response.setSapRefPoNo(allocateOrder.getSapRefPoNo());
        response.setSapSalesOrgId(allocateOrder.getSapSalesOrgId());
        response.setSapChannel(allocateOrder.getSapChannel());
        response.setMessage(allocateOrder.getMessage());
        response.setStatus(allocateOrder.getStatus() == null? null: allocateOrder.getStatus() +"");
        response.setBranchCustomersCode(allocateOrder.getBranchCustomersCode());
        //sap信贷校验
        response.setCreditCheck(allocateOrder.getCreditCheck());
        response.setCreditCheckStatus(allocateOrder.getCreditCheckStatus());
        if (StringUtils.isNotBlank(allocateOrder.getBranchCustomersCode())){
            Map<String, AllocateOrderGetCustomerResponse> customerMap = InfoUtil.getCustomerMap(Lists.newArrayList(allocateOrder.getBranchCustomersCode()));
            if (customerMap != null){
                AllocateOrderGetCustomerResponse customerResponse = customerMap.get(allocateOrder.getBranchCustomersCode());
                if (customerResponse != null){
                    response.setBranchCustomersName(customerResponse.getCustomerName());
                }

            }
//            AllocateOrderGetCustomerResponse branchCustomer = InfoUtil.getCustomer(allocateOrder.getBranchCustomersCode());
//            if (branchCustomer != null){
//                response.setBranchCustomersName(branchCustomer.getCustomerName());
//            }
        }
//        response.setBranchCustomersName(allocateOrder.getBranchCustomersName());
        //货品明细
        AllocateOrderDetailLoadListRequest allocateOrderDetailLoadListRequest = new AllocateOrderDetailLoadListRequest();
        allocateOrderDetailLoadListRequest.setAllocateOrderId(allocateOrder.getId());
        Result<List<AllocateOrderDetail>> scItemsResult = allocateOrderDetailService.loadAllocateOrderDetailList(allocateOrderDetailLoadListRequest);
//        List<AllocateOrderScItemDetailDTO> scItemDetailDTOS = Lists.newArrayList();
//        if (scItemsResult != null && CollectionUtils.isNotEmpty(scItemsResult.getResult())){
//            for (AllocateOrderDetail detail : scItemsResult.getResult()) {
//                AllocateOrderScItemDetailDTO scItemDetailDTO = new AllocateOrderScItemDetailDTO();
//                //行号
//                scItemDetailDTO.setLineNo(detail.getLineNo());
//                scItemDetailDTO.setOutAllocateOrderLineId(detail.getOutAllocateOrderLineId());
//                scItemDetailDTO.setAllocateApplyOrderLineId(detail.getAllocateApplyOrderLineId());
//                scItemDetailDTO.setScItemCode(detail.getScItemCode());
//                String scItemName = InfoUtil.getScItemName(detail.getScItemId());
//                scItemDetailDTO.setScItemName(scItemName);
//                scItemDetailDTO.setGoodsId(detail.getScItemId());
//                scItemDetailDTO.setTitle(scItemName);
//                scItemDetailDTO.setId(detail.getScItemId());
//                scItemDetailDTO.setConfirmQuantity(detail.getConfirmQuantity());
//                // TODO 交货数量
//                scItemDetailDTO.setDeliveryQuantity(null);
//                scItemDetailDTO.setShipQuantity(InfoUtil.toStr(detail.getShipQuantity()));
//                scItemDetailDTO.setReceivedQuantity(InfoUtil.toStr(detail.getReceiveQuantity()));
//                scItemDetailDTO.setNotIssuedQuantity(InfoUtil.subtract(detail.getConfirmQuantity(),detail.getShipQuantity()));
//                scItemDetailDTO.setTransQuantity(InfoUtil.subtract(detail.getShipQuantity(),detail.getReceiveQuantity()));
//                scItemDetailDTO.setUnit(detail.getUnit());
//                scItemDetailDTO.setPrice(detail.getPrice());
//                // TODO 折后金额
//                scItemDetailDTO.setDiscountPrice(null);
//                scItemDetailDTO.setDeliveryDiscountAmt(null);
//                scItemDetailDTO.setShippedDiscountAmt(null);
//                scItemDetailDTO.setTaxRate(detail.getTaxRate());
//                scItemDetailDTO.setExpectedProduceDate(detail.getExpectedProduceDate());
//                scItemDetailDTO.setClosed(detail.getClose());
//                scItemDetailDTO.setClosedDesc(Objects.equals(detail.getClose(),Boolean.TRUE)?"是":"否");
//                scItemDetailDTO.setOrderReasonDesc(EnumUtils.getOrderReason(allocateOrder.getOrderReason()));
//                scItemDetailDTO.setGiftQuantity(detail.getGiftQuantity());
//
//                scItemDetailDTOS.add(scItemDetailDTO);
//            }
//        }
//        response.setAllocateOrderScItemDetailDTOS(scItemDetailDTOS);

        //关联出入库单
        response.setBeginDate(allocateOrder.getBeginDate());
        response.setApplyOrgId(allocateOrder.getApplyOrgId());
        response.setThirdAllocateOrderId(allocateOrder.getThirdAllocateOrderId());
        response.setOrderTag(allocateOrder.getOrderTag());
        response.setPriority(allocateOrder.getPriority());
        response.setFulfillmentTypeCode(allocateOrder.getFulfillmentTypeCode());
        response.setAutoFulfillment(allocateOrder.getAutoFulfillment());
        response.setRelatedAllocateOrderCode(allocateOrder.getRelatedAllocateOrderCode());
        response.setTransferWarehouseId(allocateOrder.getTransferWarehouseId());
        response.setCompleteTime(allocateOrder.getCompleteTime());
        response.setConfirmTime(allocateOrder.getConfirmTime());
        if (StringUtils.isNotBlank(allocateOrder.getFeatures())) {
            try {
                HashMap<String, String> featureMap = parseStringToMap(allocateOrder.getFeatures());
                response.setFeatures(featureMap);
            } catch (Exception e) {
                // ignore
                log.error("AllocateOrderReadRepositoryImpl.parseStringToMap,features:{}",request.getFeatures());
            }
        }
        return response;
    }

    public HashMap<String, String> parseStringToMap(String str) {
        HashMap<String, String> map = new HashMap<>();

        if (str != null && str.startsWith("{") && str.endsWith("}")) {
            // 去除首尾的大括号
            String content = str.substring(1, str.length() - 1);
            String[] pairs = content.split(", ");
            for (String pair : pairs) {
                int equalsIndex = pair.indexOf('=');
                if (equalsIndex > 0) {
                    String key = pair.substring(0, equalsIndex);
                    String value = pair.substring(equalsIndex + 1);
                    map.put(key, value);
                }
            }
        }

        return map;
    }

    @Override
    public AllocateOrderSDO query(AllocateOrderDetailsQueryRequest allocateOrderDetailsQueryRequest) {
        AllocateOrderLoadListRequest request = new AllocateOrderLoadListRequest();
        if (StringUtils.isNotBlank(allocateOrderDetailsQueryRequest.getAllocateOrderId())){
            request.setId(Long.valueOf(allocateOrderDetailsQueryRequest.getAllocateOrderId()));
        }else if(StringUtils.isNotBlank(allocateOrderDetailsQueryRequest.getCode())){
            request.setCode(allocateOrderDetailsQueryRequest.getCode());
        }else if(StringUtils.isNotBlank(allocateOrderDetailsQueryRequest.getOutAllocateOrderId())){
            request.setOutAllocateOrderId(allocateOrderDetailsQueryRequest.getOutAllocateOrderId());
        }else {
            return null;
        }
        Result<List<AllocateOrder>> result = allocateOrderService.loadAllocateOrderList(request);
        if (result == null || CollectionUtils.isEmpty(result.getResult())){
            return null;
        }
        AllocateOrder allocateOrder = result.getResult().get(0);
//        AllocateOrder allocateOrder = allocateOrderService.loadAllocateOrder(request);
        return JsonUtil.convert(allocateOrder,AllocateOrderSDO.class);
    }

//    @Override
//    public List<AllocateOrderSDO> search(AllocateOrderDetailSearchRequest request) {
//        return null;
//    }

    @Override
    public List<AllocateOrderSDO> queryAllocateOrderSDOByIds(List<Long> ids) {
        QueryListRequest r = new QueryListRequest();
        r.setStart(0);
        r.setLimit(1000);
        r.setIdList(ids);
        QueryListResponse response =
        allocateOrderService.queryList(r);
        List<AllocateOrderSDO> sdos = JsonUtil.convertList(response.getResult(),AllocateOrderSDO.class);
//        response.getResult()
        return sdos;
    }

    @Override
    public List<AllocateOrderSDO> queryByAllocateApplyOrderIdList(List<Long> allocateApplyOrderIdList) {
        QueryByAllocateApplyOrderIdListRequest request = new QueryByAllocateApplyOrderIdListRequest();
        request.setAllocateApplyOrderIdList(allocateApplyOrderIdList);
        QueryByAllocateApplyOrderIdListResponse response =
        allocateOrderService.queryByAllocateApplyOrderIdList(request);
        return JsonUtil.convertList(response.getResult(),AllocateOrderSDO.class);
    }

    @Override
    public List<AllocateOrderSDO> queryByAllocateApplyOrderCode(String allocateApplyOrderCode) {
        if (StringUtils.isBlank(allocateApplyOrderCode)){
            return Collections.emptyList();
        }
        AllocateOrderLoadListRequest request = new AllocateOrderLoadListRequest();
        request.setAllocateApplyOrderCode(allocateApplyOrderCode);
        request.setLimit(800);
        Result<List<AllocateOrder>> result = allocateOrderService.loadAllocateOrderList(request);

//        AllocateApplyOrderLoadListRequest request = new AllocateApplyOrderLoadListRequest();
//        request.setCode(allocateApplyOrderCode);
//        Result<List<AllocateApplyOrder>> result =
//                allocateApplyOrderService.loadAllocateApplyOrderList(request);
        if (result == null ||  CollectionUtils.isEmpty(result.getResult())){
            return Collections.emptyList();
        }
        List<AllocateOrderSDO> data = JsonUtil.convertList(result.getResult(),AllocateOrderSDO.class);
        return data;
    }

    /**
     * 获取单个客户信息
     * @param code
     * @return
     */
    @Override
    public AllocateOrderGetCustomerResponse getCustomer(String code) {
        PageQueryAddressListRequest request = new PageQueryAddressListRequest();
        request.setCustomerCode(code);
        PageQueryAddressListResponse response = otsPlatformEnhanceService.pageQueryAddressList(request);
        if (response == null || response.getResult() == null) {return null;}
        JSONArray array = JSONArray.parseArray(JSON.toJSONString(response.getResult()));
        if (array == null || array.size() == 0) {return null;}
        JSONObject object = array.getJSONObject(0);
        AllocateOrderGetCustomerResponse r = new AllocateOrderGetCustomerResponse();
        r.setCustomerName(object.getString("customerName"));
        r.setCustomerAddress(object.getString("address"));
        r.setCustomerAddressName(object.getString("addressName"));
        r.setCustomer(code);
        return r;
    }

    /**
     * TODO 获取逻辑仓库
     * @param id
     * @return
     */
    @Override
    public AllocateOrderGetAreaResponse getArea(String id) {
//        QueryCargoZoneByIdResponse response =
//                unifiedInventoryService.queryCargoZoneById();

        AllocateOrderGetAreaResponse r = new AllocateOrderGetAreaResponse();
        return r;
    }

    @Override
    public AllocateOrderGetWarehouseResponse getWarehouse(String id) {
//        unifiedInventoryService.queryWarehouseById();
        AllocateOrderGetWarehouseResponse r = new AllocateOrderGetWarehouseResponse();
        return r;
    }

    @Override
    public AllocateOrderGetOrganizationResponse getOrganization(String id) {

        GetOrganiztionByIdRequest getOrganiztionByIdRequest = new GetOrganiztionByIdRequest();
        if (StringUtils.isNotBlank(id)){
            getOrganiztionByIdRequest.setId(id.trim());
        }
        OrganizationSDO org = otsPlatformEnhanceService.getOrganiztionById(getOrganiztionByIdRequest);
        AllocateOrderGetOrganizationResponse response = new AllocateOrderGetOrganizationResponse();
        if (org != null){
            response.setId(org.getId());
            response.setName(org.getName());
            response.setCode(org.getCode());
        }
        return response;
//        BaselineGetOrganizationByIdsRequest r = new BaselineGetOrganizationByIdsRequest();
//        if (StringUtils.isNotBlank(id)){
//            r.setIds(Lists.newArrayList(id));
//        }
//        Object obj = baseDataService.baselineGetOrganizationByIds(r);
//        String s = JSON.toJSONString(obj);
//        List<AllocateOrderDetailBatchGetOrgResponse> responses = convertBatchOrg(s);
//        AllocateOrderGetOrganizationResponse response = new AllocateOrderGetOrganizationResponse();
//        if (CollectionUtils.isNotEmpty(responses)){
//            AllocateOrderDetailBatchGetOrgResponse orgResponse = responses.get(0);
//            response.setId(orgResponse.getId());
//            response.setName(orgResponse.getName());
//            response.setCode(orgResponse.getCode());
//        }
//        return response;
    }
    public static List<AllocateOrderDetailBatchGetOrgResponse> convertBatchOrg(Object obj){
        JSONObject o = JSONObject.parseObject(JSONObject.toJSONString(obj));
        if (o != null){
            JSONArray array = o.getJSONArray("result");
            if (array != null && array.size() > 0){
                List<AllocateOrderDetailBatchGetOrgResponse> responses = Lists.newArrayList();
                for (int i = 0; i< array.size();i++){
                    JSONObject j = array.getJSONObject(i).getJSONObject("organizationSDO");

                    AllocateOrderDetailBatchGetOrgResponse r =
                            JsonUtil.convert(j,AllocateOrderDetailBatchGetOrgResponse.class);
                    responses.add(r);
                }
                return responses;
            }
        }
        return null;
    }

    // TODO 获取客户信息 通过 库区id
    @Override
    public AllocateOrderGetCustomerResponse getCustomer(AllocateOrderGetCustomerRequest request) {
        QueryCargoZoneByIdRequest queryCargoZoneByIdRequest = new QueryCargoZoneByIdRequest();
        if (request.getAreaId() != null){
            queryCargoZoneByIdRequest.setCargoZoneIdList(Lists.newArrayList(request.getAreaId()));
        }
        QueryCargoZoneByIdResponse response =
        unifiedInventoryService.queryCargoZoneById(queryCargoZoneByIdRequest);
        Map wms = convert(response);
        String customerCode = wms.get("sapDeliveryBPCode") == null? null:wms.get("sapDeliveryBPCode").toString();
        if (customerCode != null ){
            AllocateOrderGetCustomerResponse customerResponse = getCustomer(customerCode);
            return customerResponse;
        }
        return null;

    }

    public static Map<String,Object> convert(QueryCargoZoneByIdResponse response){
        if (response != null && CollectionUtils.isNotEmpty(response.getResult())){
            return JsonUtil.convert(response.getResult().get(0),Map.class);
        }
        return Maps.newHashMap();
    }

    @Override
    public List<AllocateOrderBatchGetWarehouseResponse> getWarehouse(AllocateOrderGetWarehouseRequest request) {
        WmsQueryWarehouseZoneListRequest zoneListRequest = new WmsQueryWarehouseZoneListRequest();
        if (StringUtils.isNotBlank(request.getType())){
            zoneListRequest.setType(Integer.parseInt(request.getType()));
        }
        WmsQueryWarehouseZoneListResponse response = unifiedInventoryService.wmsQueryWarehouseZoneList(zoneListRequest);
        List<AllocateOrderBatchGetWarehouseResponse> responses = Lists.newArrayList();
        if (CollectionUtils.isNotEmpty(response.getResult())){
            for (WarehouseInfo info : response.getResult()){
                AllocateOrderBatchGetWarehouseResponse warehouseResponse = new AllocateOrderBatchGetWarehouseResponse();
                warehouseResponse.setLabel(info.getName());
                warehouseResponse.setValue(info.getId());
                responses.add(warehouseResponse);
            }
        }
        return responses;
    }

    public static Map<String,String> getWmsMap(Result<List<OuiAllocateOrderDetailIndex>> result){
        Map<String,String> map = Maps.newHashMap();
        if (result == null || CollectionUtils.isEmpty(result.getResult())){
            return map;
        }
        List<String> ids = result.getResult().stream().filter(Objects::nonNull)
                .flatMap(x-> Stream.of(x.getMainShipAreaId(),x.getMainReceiveAreaId(),
                        x.getMainShipWarehouseId(),x.getMainReceiveWarehouseId()))
                .filter(Objects::nonNull)
                .filter(y->StringUtils.isNotBlank(y))
                .distinct()
                .collect(Collectors.toList());
//                        .filter(x->StringUtils.isNotBlank(x.getMainShipAreaId()))
        Map<String, String> wmsMap = InfoUtil.getWmsNameMap(ids);
        return wmsMap;
    }

    // 在途单据es
    public List<AloocateOrderGetTransResponse> getTransOrderES(AloocateOrderGetTransRequest aloocateOrderGetTransRequest){
        //接入es
        AllocateOrderDetailSearchRequest request = new AllocateOrderDetailSearchRequest();
        if (aloocateOrderGetTransRequest != null){
            if (StringUtils.isNotBlank(aloocateOrderGetTransRequest.getScItemId())){
                request.setScItemIdList(Lists.newArrayList(aloocateOrderGetTransRequest.getScItemId()));
            }
            if (StringUtils.isNotBlank(aloocateOrderGetTransRequest.getReceiveAreaId())){
                request.setReceiveAreaId(aloocateOrderGetTransRequest.getReceiveAreaId());
            }

            request.setStart(aloocateOrderGetTransRequest.getStart() == null?0:aloocateOrderGetTransRequest.getStart());
            request.setLimit(aloocateOrderGetTransRequest.getLimit() == null?0:aloocateOrderGetTransRequest.getLimit());

        }

//        Result<List<OuiAllocateOrderDetailIndex>> search = ouiAllocateOrderDetailIndexService.search(request);
        Result<List<OuiAllocateOrderDetailIndex>> search = ouiAllocateOrderDetailIndexService.searchTranfersOrders(request);
        List<AloocateOrderGetTransResponse> list = Lists.newArrayList();
        if (search != null && CollectionUtils.isNotEmpty(search.getResult())){

            Map<String, String> wmsMap = getWmsMap(search);
            for (OuiAllocateOrderDetailIndex index : search.getResult()) {
                AloocateOrderGetTransResponse response = new AloocateOrderGetTransResponse();
                response.setCode(index.getMainCode());
                response.setLineNo(index.getSubLineNo() == null?null:index.getSubLineNo().toString());
                String scItemName = InfoUtil.getScItemName(index.getSubScItemId());
                response.setScItemName(scItemName);
                response.setScItemCode(index.getSubScItemCode());
                response.setReceiveAreaName(wmsMap.get(index.getMainReceiveAreaId()));
                //发货仓
                response.setShipAreaName(wmsMap.get(index.getMainShipAreaId()));
                response.setTransQuantity(InfoUtil.subtract(index.getSubShipQuantity(),index.getSubReceiveQuantity()));
                response.setExpectedDeliveryDate(TimeUtil.getDateByLong(index.getSubExpectedDeliveryDate()));
                list.add(response);
            }
        }
        return list;
    }


    @Override
    @RepositoryInvoker(printLog = true)
    public Result<List<AloocateOrderGetTransResponse>> getTransOrder(AloocateOrderGetTransRequest aloocateOrderGetTransRequest) {
//        return getTransOrderES(aloocateOrderGetTransRequest);
        //接入es
        AllocateOrderDetailSearchRequest request = new AllocateOrderDetailSearchRequest();
        if (aloocateOrderGetTransRequest != null){
            if (StringUtils.isNotBlank(aloocateOrderGetTransRequest.getScItemId())){
                request.setScItemIdList(Lists.newArrayList(aloocateOrderGetTransRequest.getScItemId()));
            }
            if (StringUtils.isNotBlank(aloocateOrderGetTransRequest.getReceiveAreaId())){
                request.setReceiveAreaId(aloocateOrderGetTransRequest.getReceiveAreaId());
            }

            request.setStart(aloocateOrderGetTransRequest.getStart() == null?0:aloocateOrderGetTransRequest.getStart());
            request.setLimit(aloocateOrderGetTransRequest.getLimit() == null?0:aloocateOrderGetTransRequest.getLimit());

        }

//        Result<List<OuiAllocateOrderDetailIndex>> search = ouiAllocateOrderDetailIndexService.search(request);
        Result<List<OuiAllocateOrderDetailIndex>> search = ouiAllocateOrderDetailIndexService.searchTranfersOrders(request);
        List<AloocateOrderGetTransResponse> list = Lists.newArrayList();
        if (search != null && CollectionUtils.isNotEmpty(search.getResult())){

            Map<String, String> wmsMap = getWmsMap(search);
            for (OuiAllocateOrderDetailIndex index : search.getResult()) {
                AloocateOrderGetTransResponse response = new AloocateOrderGetTransResponse();
                response.setCode(index.getMainCode());
                response.setLineNo(index.getSubLineNo() == null?null: index.getSubLineNo().toString());
                String scItemName = InfoUtil.getScItemName(index.getSubScItemId());
                response.setScItemName(scItemName);
                response.setScItemCode(index.getSubScItemCode());
                response.setReceiveAreaName(wmsMap.get(index.getMainReceiveAreaId()));
                //发货仓
                response.setShipAreaName(wmsMap.get(index.getMainShipAreaId()));
                response.setTransQuantity(InfoUtil.subtract(index.getSubShipQuantity(),index.getSubReceiveQuantity()));
                response.setExpectedDeliveryDate(TimeUtil.getDateByLong(index.getSubExpectedDeliveryDate()));
                list.add(response);
            }
        }
        Result result = Result.success(list);
        result.setTotal(search.getTotal());
        return result;
    }


    @Override
    public List<AllocateOrderDetailSDO> queryListByAllocateOrderIds(List<Long> ids) {
        QueryListByIdsRequest request = new QueryListByIdsRequest();
        if (CollectionUtils.isNotEmpty(ids)){
            request.setAllocateOrderIds(ids);
        }
        QueryListByIdsResponse queryListByIdsResponse = allocateOrderDetailService.queryListByIds(request);
        if (queryListByIdsResponse != null && CollectionUtils.isNotEmpty(queryListByIdsResponse.getResult())){
            List<AllocateOrderDetailSDO> detailSDOS = JsonUtil.convertList(queryListByIdsResponse.getResult(),
                    AllocateOrderDetailSDO.class);
            return detailSDOS;
        }
        List<AllocateOrderDetailSDO> list = Lists.newArrayList();
        return list;
    }


    public  WmsSDO getWmsSDO(String areaId){
        if (StringUtils.isNotBlank(areaId)){
            QueryCargoZoneByIdRequest queryCargoZoneByIdRequest = new QueryCargoZoneByIdRequest();
            queryCargoZoneByIdRequest.setCargoZoneIdList(Lists.newArrayList(areaId));
            QueryCargoZoneByIdResponse shipAreaQuery = unifiedInventoryService.queryCargoZoneById(queryCargoZoneByIdRequest);
            return getWmsSDO(shipAreaQuery);
        }
        return new WmsSDO();
    }

    public static WmsSDO getWmsSDO(QueryCargoZoneByIdResponse response){
        WmsSDO wmsSDO = new WmsSDO();
        if (response !=null && CollectionUtils.isNotEmpty(response.getResult())){
            JSONArray array = JSON.parseArray(JSON.toJSONString(response.getResult()));
            if (array != null && array.size() > 0){
                JSONObject data = array.getJSONObject(0);
//                wmsSDO.setInventoryCode(data.getString("code"));
                wmsSDO.setInventoryCode(data.getString("warehouseCode"));
                wmsSDO.setFactoryCode(data.getString("sapFactoryCode"));
                wmsSDO.setSapCompanyCode(data.getString("sapCompanyCode"));
                wmsSDO.setSapSalesBPCode(data.getString("sapSaleBPCode"));//有点问题的.
                wmsSDO.setSapDeliveryBPCode(data.getString("sapDeliveryBPCode"));
                wmsSDO.setSapInternalDeliveryBPCode(data.getString("sapInternalDeliveryBPCode"));
                wmsSDO.setSapInternalSalesBPCode(data.getString("sapInternalSalesBPCode"));
                wmsSDO.setSapSalesOrgId(data.getString("saleOrgId"));
//                wmsSDO.setSapSalesOrgId(data.getString("sapSaleOrgId"));
                wmsSDO.setName(data.getString("name"));
                wmsSDO.setType(data.getString("type"));

//                if (StringUtils.isNotBlank(data.getString("features"))){
//                    JSONObject features = JSON.parseObject(data.getString("features"));
//                    if (features != null){
//                        wmsSDO.setSapCompanyCode(features.getString(""));
//                    }
//                }
            }
        }
        return wmsSDO;
    }
    /**
     * 获取退单信息
     * @param request
     * @return
     */
    @Override
    public AllocateOrderReturnOrderInfoResponse getReturnOrderInfo(AllocateOrderReturnOrderRequest request) {
        AllocateOrderReturnOrderInfoResponse response = new AllocateOrderReturnOrderInfoResponse();
        if (request == null || StringUtils.isBlank(request.getAllocateOrderId())
                || CollectionUtils.isEmpty(request.getAllocateOrderScItemDetailDTOS())){
            return response;
        }
//        LoadAllocateOrderRequest loadAllocateOrderRequest = new LoadAllocateOrderRequest();
//        loadAllocateOrderRequest.setId(request.getAllocateOrderId());
//        AllocateOrder allocateOrder = allocateOrderService.loadAllocateOrder(loadAllocateOrderRequest);
        AllocateOrderLoadListRequest allocateOrderLoadListRequest = new AllocateOrderLoadListRequest();
        allocateOrderLoadListRequest.setOutAllocateOrderId(request.getAllocateOrderId());
        Result<List<AllocateOrder>> listResult = allocateOrderService.loadAllocateOrderList(allocateOrderLoadListRequest);
        if (listResult  == null || CollectionUtils.isEmpty(listResult.getResult())){
            return response;
        }
        AllocateOrder allocateOrder = listResult.getResult().get(0);
//        if (allocateOrder == null){
//            return response;
//        }
        response.setTypeDesc(EnumUtils.getAllocateOrderType(allocateOrder.getType()));
        // 组织
        if (StringUtils.isNotBlank(allocateOrder.getApplyOrgId())){
            AllocateOrderGetOrganizationResponse orgResponse = InfoUtil.getOrganizationById(allocateOrder.getApplyOrgId());
            response.setApplyOrgName(orgResponse.getName());
        }
        response.setProductGroupDesc("常温");
        response.setReturnOrderDesc("是");
        response.setAllocateApplyOrderCode(allocateOrder.getAllocateApplyOrderCode());
        response.setOutAllocateOrderId(allocateOrder.getOutAllocateOrderId());
        response.setCreateTime(new Date());
        //创建人 用当前的创建人
//        QueryUserByIdRequest
        LoginUser loginUser = epochLoginUserService.getLoginUser();
        if (loginUser != null){
            response.setCreator(loginUser.getRealName());
        }
        response.setCreator(NameUtil.getRealName(allocateOrder.getCreator()));
        response.setDocDate(InfoUtil.salesDocDate());
        response.setDocDateStr(TimeUtil.formatYYYY_MM_dd(response.getDocDate()));
        //由3天后 -> 改成1天后
        response.setExpectedDeliveryDate(InfoUtil.afterDays(response.getDocDate(),1));
        response.setExpectedDeliveryDateStr(TimeUtil.formatYYYY_MM_dd(response.getExpectedDeliveryDate()));
//        response.setModifier(NameUtil.getRealName(allocateOrder.getUpdater()));
//        response.setUpdateTime(allocateOrder.getGmt_modified());
        response.setOrderReasonDesc(EnumUtils.getOrderReason(request.getOrderReason()));
        response.setShipAreaId(allocateOrder.getShipAreaId());
        response.setReceiveAreaId(allocateOrder.getReceiveAreaId());
        WmsSDO shipWmsSDO = getWmsSDO(allocateOrder.getShipAreaId());
        if (StringUtils.isBlank(allocateOrder.getReceiveAreaId())){
            AllocateOrderGetInOutOrderRequest allocateOrderGetInOutOrderRequest = new AllocateOrderGetInOutOrderRequest();
            allocateOrderGetInOutOrderRequest.setAllocateOrderId(allocateOrder.getId().toString());
            allocateOrderGetInOutOrderRequest.setStatusList(Lists.newArrayList(WmsStatusEnum.Normal.getValue()));
            allocateOrderGetInOutOrderRequest.setSize(MAX_PAGE_SIZE);
            GetListOutinForAllocationResponse listOutinForAllocation = otsUnifiedInventoryService.getListOutinForAllocation(allocateOrderGetInOutOrderRequest);
            String receiveAreaId = getReceiveAreaId(listOutinForAllocation);
            if (StringUtils.isNotBlank(receiveAreaId)){
//                allocateOrder.setReceiveAreaId(receiveAreaId);
                response.setReceiveAreaId(receiveAreaId);
            }
        }
        WmsSDO receiveWmsSDO = getWmsSDO(allocateOrder.getReceiveAreaId());
        //发货仓组织
        if (shipWmsSDO !=null){
//            AllocateOrderGetOrganizationResponse shipOrg = InfoUtil.getOrganizationById(shipWmsSDO.getSapSalesOrgId());
            AllocateOrderGetOrganizationResponse shipOrg = InfoUtil.getOrganizationById(allocateOrder.getShipOrgId());
            response.setShipOrgName(shipOrg.getName());
            response.setShipAreaName(shipWmsSDO.getName());
        }
        if (receiveWmsSDO != null){
//            AllocateOrderGetOrganizationResponse receiveOrg = InfoUtil.getOrganizationById(receiveWmsSDO.getSapSalesOrgId());
            AllocateOrderGetOrganizationResponse receiveOrg = InfoUtil.getOrganizationById(allocateOrder.getReceiveOrgId());
            response.setReceiveOrgName(receiveOrg.getName());
            response.setReceiveAreaName(receiveWmsSDO.getName());
        }
        if (StringUtils.isNotBlank(allocateOrder.getAddressCode())){
            AllocateOrderGetCustomerResponse customerByAddressCode = InfoUtil.getCustomerByAddressCode(allocateOrder.getAddressCode());
            if (customerByAddressCode != null){
                response.setCustomer(customerByAddressCode.getCustomer());
                response.setCustomerName(customerByAddressCode.getCustomerName());
                response.setCustomerAddress(customerByAddressCode.getCustomerAddress());
                response.setCustomerAddressName(customerByAddressCode.getCustomerAddressName());
            }
        }
        //总部客户的
        if (receiveWmsSDO != null){
            AllocateOrderGetCustomerResponse customer = InfoUtil.getCustomer(receiveWmsSDO.getSapDeliveryBPCode());
            if (customer != null){
                response.setSapCustomerName(customer.getCustomerName());
                response.setSapCustomerAddress(customer.getCustomerAddress());
                response.setSapCustomerAddressName(customer.getCustomerAddressName());
            }
        }
        response.setShipMethodDesc(InfoUtil.getShipMethodDesc(allocateOrder.getShipMethod()));
        response.setSapInternalSalesBPCode(receiveWmsSDO.getSapInternalSalesBPCode());
        response.setSapInternalDeliveryBPCode(receiveWmsSDO.getSapInternalDeliveryBPCode());
        response.setSapDeliveryBPCode(receiveWmsSDO.getSapDeliveryBPCode());
        response.setSapSalesBPCode(receiveWmsSDO.getSapSalesBPCode());
        response.setRemark(allocateOrder.getRemark());
        response.setSapCostCenter(allocateOrder.getSapCostCenter());
        response.setSapRefPoNo(allocateOrder.getSapRefPoNo());
        response.setSapChannel(allocateOrder.getSapChannel());
        response.setSapSalesOrgId(allocateOrder.getSapSalesOrgId());
        response.setSaleOrganizationCode(allocateOrder.getSapSalesOrgId());

        List<AllocateOrderReturnOrderInfoScItemDTO> scItemDTOList = Lists.newArrayList();


        for (AllocateOrderScItemDetailDTO dto:  request.getAllocateOrderScItemDetailDTOS()) {
            AllocateOrderDetailLoadListRequest allocateOrderDetailLoadListRequest = new AllocateOrderDetailLoadListRequest();
            allocateOrderDetailLoadListRequest.setAllocateOrderId(allocateOrder.getId());
            allocateOrderDetailLoadListRequest.setScItemId(dto.getScItemId());
            Result<List<AllocateOrderDetail>> result = allocateOrderDetailService.loadAllocateOrderDetailList(allocateOrderDetailLoadListRequest);
            if (result == null || CollectionUtils.isEmpty(result.getResult())) {
                continue;
            }
            AllocateOrderDetail allocateOrderDetail = result.getResult().get(0);
            AllocateOrderReturnOrderInfoScItemDTO scItemDTO = new AllocateOrderReturnOrderInfoScItemDTO();
            scItemDTO.setLineNo(allocateOrderDetail.getLineNo() == null?null:allocateOrderDetail.getLineNo().toString());
            String scItemName = InfoUtil.getScItemName(allocateOrderDetail.getScItemId());
            scItemDTO.setScItemName(scItemName);
            scItemDTO.setScItemId(allocateOrderDetail.getScItemCode());
            scItemDTO.setTitle(scItemName);
            scItemDTO.setQuantity(dto.getQuantity());
            scItemDTO.setExpectedProductDate(allocateOrderDetail.getExpectedProduceDate());
            scItemDTO.setExpectedDeliveryDate(allocateOrderDetail.getExpectedDeliveryDate());
            scItemDTO.setPrice(allocateOrderDetail.getPrice());
//            scItemDTO.setRemark(allocateOrderDetail.getRemarks());
            scItemDTO.setApplyQuantity(dto.getQuantity());
//            scItemDTO.setProductDate(allocateOrderDetail.getExpectedProduceDate());
            scItemDTO.setProductDate(TimeUtil.formatYYYY_MM_dd(dto.getExpectedProduceDate()));
            scItemDTO.setRemark(dto.getRemarks());
            scItemDTOList.add(scItemDTO);
            String scItemId =  InfoUtil.getScItemIdByOutCode(scItemDTO.getScItemId());
            GetListWarehouseStock2Request getListWarehouseStock2Request = new GetListWarehouseStock2Request();
//            getListWarehouseStock2Request.setWarehouseAreaId(allocateOrder.getShipAreaId());
            getListWarehouseStock2Request.setWarehouseAreaId(response.getReceiveAreaId());
            getListWarehouseStock2Request.setType("1");
            if (StringUtils.isNotBlank(scItemId)){
                getListWarehouseStock2Request.setGoodsId(scItemId);
            }
            Result<List<WarehouseInventory>> listWarehouseStock2 = otsUnifiedInventoryService.getListWarehouseStock2(getListWarehouseStock2Request);
            if (listWarehouseStock2 != null && CollectionUtils.isNotEmpty(listWarehouseStock2.getResult())){
//                WarehouseInventory warehouseInventory = listWarehouseStock2.getResult().stream().filter(x -> Objects.equals(x.getGoodsCode(), allocateOrderDetail.getScItemCode()))
//                        .findFirst().orElse(null);
                WarehouseInventory warehouseInventory = listWarehouseStock2.getResult().get(0);
                if (warehouseInventory != null){
                    scItemDTO.setAvailableQuantity(warehouseInventory.getAvailableQuantityFormat());
                    if (CollectionUtils.isNotEmpty(warehouseInventory.getDoms())){
                        String dom = warehouseInventory.getDoms().stream().filter(x -> StringUtils.isNotBlank(x.getDom()))
                                .sorted(Comparator.comparing(WarehouseInventoryDoms::getDom)).findFirst().get().getDom();
                        scItemDTO.setExpectedProductDate(TimeUtil.parseYYYY_MM_dd(dom));
                    }
                }
            }
        }
        response.setScItemDTOList(scItemDTOList);
        response.setAllocateOrderReturnOrderRequest(request);

        return response;
    }

    @Override
    public List<AllocateOrderSDO> search(AllocateOrderDetailSearchRequest request) {
        return null;
    }


    /**
     * 查询冻结及未确认金额
     * @param companyId
     * @return
     */
    @Override
    public Result<FrozenAndUnconfirmedAmountResponse> queryFrozenAndUnconfirmedAmount(String companyId) {
        if (StringUtils.isBlank(companyId)){
//            return Result.fail("OTS-03-005-00-15-400","分子公司id不能为空");
            throw new FacadeException("OTS-03-005-00-15-400");
        }

        List<AllocateOrderDetail> frozenAllocateOrderDetails = queryFrozenAllocateOrderDetails(companyId);
        log.info("frozenAllocateOrderDetails:{}",JSON.toJSONString(frozenAllocateOrderDetails));
        List<AllocateOrderDetail> unfrozenUnconfirmedAllocateOrderDetails = queryUnconfirmedAllocateOrderDetails(companyId);
        log.info("unfrozenUnconfirmedAllocateOrderDetails:{}",unfrozenUnconfirmedAllocateOrderDetails);

        String frozenOrderAmount = calcFrozenOrderAmount(frozenAllocateOrderDetails);
        String unfrozenUnconfirmedOrderAmount = calcUnfrozenUnconfirmedOrderAmount(unfrozenUnconfirmedAllocateOrderDetails);
        FrozenAndUnconfirmedAmountResponse response = new FrozenAndUnconfirmedAmountResponse();
        response.setFrozenOrderAmount(frozenOrderAmount);
        response.setUnfrozenUnconfirmedOrderAmount(unfrozenUnconfirmedOrderAmount);
        log.info("frozenAndUnconfirmedAmountResponse:{}",JSON.toJSONString(response));

        return Result.success(response);
    }

    //计算冻结调拨单金额
    private String calcFrozenOrderAmount(List<AllocateOrderDetail> details){
        return Nullable.stream(details).map(detail -> {
            //（订单数量-交货数量)*折后单价的求和总额；
            BigDecimal quantity = StringUtils.isBlank(detail.getQuantity()) ? BigDecimal.ZERO: new BigDecimal(detail.getQuantity().trim());
            BigDecimal deliveryQuantity = StringUtils.isBlank(detail.getDeliveryQuantity()) ? BigDecimal.ZERO : new BigDecimal(detail.getDeliveryQuantity().trim());
            BigDecimal price = StringUtils.isBlank(detail.getPrice()) ? BigDecimal.ZERO : new BigDecimal(detail.getPrice().trim());
            BigDecimal discountPrice = StringUtils.isBlank(detail.getSubTotalAmount()) ? price : new BigDecimal(detail.getSubTotalAmount()).divide(quantity,2,RoundingMode.HALF_UP);

            return quantity.subtract(deliveryQuantity).multiply(discountPrice);
//            if (StringUtils.isNotBlank(detail.getSubTotalAmount())){
//                return new BigDecimal(detail.getSubTotalAmount())
//            }else {
//                if (StringUtils.isBlank(detail.getPrice()) || StringUtils.isBlank(detail.getQuantity())){
//                    return BigDecimal.ZERO;
//                }
//                return new BigDecimal(detail.getPrice().trim()).multiply(new BigDecimal(detail.getQuantity().trim()));
//            }
        }).reduce(BigDecimal.ZERO,BigDecimal::add).toPlainString();
    }
    //计算未确认且不是冻结的调拨单金额
    private String calcUnfrozenUnconfirmedOrderAmount(List<AllocateOrderDetail> details){
        return Nullable.stream(details).map(detail -> {
            if (StringUtils.isBlank(detail.getQuantity())){
                return BigDecimal.ZERO;
            }
            BigDecimal quantityBigDecimal = new BigDecimal(detail.getQuantity().trim());
            BigDecimal confirmQuantityBigDecimal = StringUtils.isBlank(detail.getConfirmQuantity()) ? BigDecimal.ZERO :
                    new BigDecimal(detail.getConfirmQuantity());
            BigDecimal unConfirmQuantity = quantityBigDecimal.subtract(confirmQuantityBigDecimal);
            if (StringUtils.isNotBlank(detail.getSubTotalAmount())){
                return new BigDecimal(detail.getSubTotalAmount().trim()).divide(quantityBigDecimal,2, RoundingMode.HALF_UP)
                        .multiply(unConfirmQuantity);
            }else {
                if (StringUtils.isBlank(detail.getPrice())){
                    return BigDecimal.ZERO;
                }
                return unConfirmQuantity.multiply(new BigDecimal(detail.getPrice()));
            }
        }).reduce(BigDecimal.ZERO,BigDecimal::add).toPlainString();
    }

    /**
     * 查询冻结订单
     * 冻结订单
     * 调拨单状态：待发货、部分发货、已发货、待收货、部分收货
     * 条件1：信贷检查状态为B
     * 条件2：行拒绝原因为空
     * 条件3：行交货数量<行订单数量
     * 冻结订单金额=（订单数量-交货数量)*折后单价的求和总额；
     * @param companyId
     * @return
     */
    private List<AllocateOrderDetail> queryFrozenAllocateOrderDetails(String companyId){
        QueryFrozenOrderDetailListRequest request = new QueryFrozenOrderDetailListRequest();
        request.setApplyOrgId(companyId);
        request.setStart(0);
        request.setLimit(MAX_PAGE_SIZE);
        Result<List<AllocateOrderDetail>> listResult = allocateOrderDetailService.queryFrozenOrderDetailList(request);
        if (listResult == null || CollectionUtils.isEmpty(listResult.getResult())){
            return Lists.newArrayList();
        }
        List<AllocateOrderDetail> dataList = Lists.newArrayList();
        dataList.addAll(listResult.getResult());
        int total = listResult.getTotal();
        if (total > MAX_PAGE_SIZE){
            int totalPage = PageUtils.getTotalPage(total, MAX_PAGE_SIZE);
            List<Future<List<AllocateOrderDetail>>> futureList = Lists.newArrayList();
            for (int page = 1; page <= totalPage; page++) {
                int finalPage = page;
                CompletableFuture<List<AllocateOrderDetail>> future = CompletableFuture.supplyAsync(() -> {
                    request.setStart(finalPage * MAX_PAGE_SIZE);
                    Result<List<AllocateOrderDetail>> result = allocateOrderDetailService.queryFrozenOrderDetailList(request);
                    if (result != null && CollectionUtils.isNotEmpty(result.getResult())){
                        return result.getResult();
                    }
                    return null;
                },threadPoolTaskExecutor);
                futureList.add(future);
            }
            Nullable.stream(futureList).forEach(listFuture -> {
                try {
                    List<AllocateOrderDetail> list = listFuture.get();
                    if (CollectionUtils.isNotEmpty(list)){
                        dataList.addAll(list);
                    }
                }catch (Throwable e){
                    log.error("queryFrozenAndUnconfirmedAmount_error",e);
                }
            });

        }
        return dataList;
    }


    /**
     * 未确认订单
     * 调拨单状态：待发货、部分发货、已发货、待收货、部分收货
     * 条件1：信贷检查状态为A\C\D\空
     * 条件2：行拒绝原因为空
     * 条件3：行交货数量<行订单数量
     * 未确认订单金额=（订单数量-确认数量）*折后单价的求和总额；
     *
     * 调拨单更新时间是0705（含当天）订单
     * @param companyId
     * @return
     */
    private List<AllocateOrderDetail> queryUnconfirmedAllocateOrderDetails(String companyId){
        QueryUnconfirmedOrderDetailListRequest request = new QueryUnconfirmedOrderDetailListRequest();
        request.setApplyOrgId(companyId);
        request.setStart(0);
        request.setLimit(MAX_PAGE_SIZE);
        Result<List<AllocateOrderDetail>> listResult = allocateOrderDetailService.queryUnconfirmedOrderDetailList(request);
        if (listResult == null || CollectionUtils.isEmpty(listResult.getResult())){
            return Lists.newArrayList();
        }
        List<AllocateOrderDetail> dataList = Lists.newArrayList();
        dataList.addAll(listResult.getResult());
        int total = listResult.getTotal();
        if (total > MAX_PAGE_SIZE){
            int totalPage = PageUtils.getTotalPage(total, MAX_PAGE_SIZE);
            List<Future<List<AllocateOrderDetail>>> futureList = Lists.newArrayList();
            for (int page = 1; page <= totalPage; page++) {
                int finalPage = page;
                CompletableFuture<List<AllocateOrderDetail>> future = CompletableFuture.supplyAsync(() -> {
                    request.setStart(finalPage * MAX_PAGE_SIZE);
                    Result<List<AllocateOrderDetail>> result = allocateOrderDetailService.queryUnconfirmedOrderDetailList(request);
                    if (result != null && CollectionUtils.isNotEmpty(result.getResult())){
                        return result.getResult();
                    }
                    return null;
                },threadPoolTaskExecutor);
                futureList.add(future);
            }
            Nullable.stream(futureList).forEach(listFuture -> {
                try {
                    List<AllocateOrderDetail> list = listFuture.get();
                    if (CollectionUtils.isNotEmpty(list)){
                        dataList.addAll(list);
                    }
                }catch (Throwable e){
                    log.error("queryFrozenAndUnconfirmedAmount_error",e);
                }
            });

        }
        return dataList;
    }


    private List<AllocateOrderDetail> queryAllocateOrderDetails(String companyId, String status){
        QueryListForStatCreditRequest queryListForStatCreditRequest = new QueryListForStatCreditRequest();
        queryListForStatCreditRequest.setApplyOrgId(companyId);
        queryListForStatCreditRequest.setCreditCheckStatus(status);
        queryListForStatCreditRequest.setStart(0);
        queryListForStatCreditRequest.setLimit(MAX_PAGE_SIZE);
        Result<List<AllocateOrderDetail>> listResult = allocateOrderDetailService.queryListForStatCredit(queryListForStatCreditRequest);
        if (listResult == null || CollectionUtils.isEmpty(listResult.getResult())){
            return Lists.newArrayList();
        }
        List<AllocateOrderDetail> dataList = Lists.newArrayList();
        dataList.addAll(listResult.getResult());
        int total = listResult.getTotal();
        if (total > MAX_PAGE_SIZE){
            int totalPage = PageUtils.getTotalPage(total, MAX_PAGE_SIZE);
            List<Future<List<AllocateOrderDetail>>> futureList = Lists.newArrayList();
            for (int page = 1; page <= totalPage; page++) {
                int finalPage = page;
                CompletableFuture<List<AllocateOrderDetail>> future = CompletableFuture.supplyAsync(() -> {
                    queryListForStatCreditRequest.setStart(finalPage * MAX_PAGE_SIZE);
                    Result<List<AllocateOrderDetail>> result = allocateOrderDetailService.queryListForStatCredit(queryListForStatCreditRequest);
                    if (result != null && CollectionUtils.isNotEmpty(result.getResult())){
                        return result.getResult();
                    }
                    return null;
                },threadPoolTaskExecutor);
                futureList.add(future);
            }
            Nullable.stream(futureList).forEach(listFuture -> {
                try {
                    List<AllocateOrderDetail> list = listFuture.get();
                    if (CollectionUtils.isNotEmpty(list)){
                        dataList.addAll(list);
                    }
                }catch (Throwable e){
                    log.error("queryFrozenAndUnconfirmedAmount_error",e);
                }
            });

        }
        return dataList;
    }

    //获取收货仓id
    String getReceiveAreaId(GetListOutinForAllocationResponse response){
        if (response != null && CollectionUtils.isNotEmpty(response.getResult())){
            for (Object data : response.getResult()) {
                if (data == null){
                    continue;
                }
                JSONObject js = JSONObject.parseObject(JSON.toJSONString(data));
                if (js == null){
                    continue;
                }
                String type = js.getString("mainOrderType");
                //1入库 2出库
                if ("1".equals(type) || "1.0".equals(type)){
                    String warehouseAreaId = js.getString("warehouseAreaId");
                    if (StringUtils.isNotBlank(warehouseAreaId)){
                        return warehouseAreaId;
                    }
                }
            }
        }
        return null;
    }

    public static List<OutWarehouseDetailDTO> getOutWarehouseDetailDTOS(GetListOutinForAllocationResponse response) {
        List<OutWarehouseDetailDTO> detailDTOS = Lists.newArrayList();
        if (response != null && CollectionUtils.isNotEmpty(response.getResult())) {
            for (Object obj : response.getResult()) {
                if (obj == null) {continue;}
                JSONObject js = JSONObject.parseObject(JSON.toJSONString(obj));
                if (js == null) {continue;}
                String type = js.getString("mainOrderType");
                if ("2".equals(type) || "2.0".equals(type)) {
                    OutWarehouseDetailDTO dto = new OutWarehouseDetailDTO();
                    dto.setOutCode(js.getString("outSubOrderId"));
                    dto.setCode(js.getString("wmsSubOrderId"));
                    dto.setCreateTime(js.getString("gmtCreate"));
                    dto.setOutSubOrderId(js.getString("outSubOrderId"));
//                dto.setStatusDesc(js.getString("mainOrderTypeDesc"));
                    dto.setScItemName(js.getString("goodsName"));
                    dto.setBatch(js.getString("batchNo"));
                    dto.setProductionDate(js.getString("dom"));
//                    dto.setQuantity(js.getString("goodsQuantity"));
                    dto.setQuantity(js.getString("goodsQuantityFormat"));
                    dto.setScItemCode(js.getString("goodsId"));
                    dto.setScItemId(js.getString("goodsId"));
                    dto.setStatus(js.getString("status"));
                    dto.setSourceSubOrderId(js.getString("sourceSubOrderId"));
                    detailDTOS.add(dto);
                }
            }
        }
        return detailDTOS;
    }
}
